package com.douqu.game.core.util;

import com.alibaba.fastjson.JSONObject;
import com.bean.core.util.EncryptUtils;
import com.bean.core.util.FileUtils;
import com.douqu.game.core.config.PlayerNameConfig;
import com.douqu.game.core.config.common.CommonData;
import com.douqu.game.core.config.common.GoodsData;
import com.douqu.game.core.config.drop.DropObject;
import com.douqu.game.core.entity.GameObject;
import com.douqu.game.core.factory.ConstantFactory;
import com.douqu.game.core.factory.DataFactory;
import com.douqu.game.core.factory.LoadFactory;
import com.douqu.game.core.util.time.TimeData;
import com.douqu.game.core.util.time.TimeUtils;
import org.yaml.snakeyaml.reader.UnicodeReader;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;

/**
 * Author : Bean
 * 2017-05-03 19:08
 */
public class LoadUtils {

    public static boolean checkNotNull(GameObject[] gameObjects, Class cls, String key, int parentId)
    {
        for(GameObject gameObject : gameObjects)
        {
            if(gameObject == null)
            {
                LogUtils.error(cls.getSimpleName() + " Load " + key + " Error -> parentId:" + parentId);
                return false;
            }
        }
        return true;
    }

    public static boolean checkCommonData(CommonData[] commonDatas, Class cls, String key, int typeKey, int parentId, boolean... notCheckValue)
    {
        for(CommonData commonData : commonDatas)
        {
            if(!commonData.check(cls, key, typeKey, parentId, notCheckValue))
                return false;
        }
        return true;
    }

    public static boolean checkDropObject(DropObject[] dropObjects, Class cls, String key, int typeKey, int parentId)
    {
        for(DropObject dropObject : dropObjects)
        {
            if(!dropObject.check(cls, key, typeKey, parentId))
                return false;
        }
        return true;
    }

    public static boolean checkProp(GoodsData[] goodsDatas, Class cls, String key, int parentId)
    {
        for(GoodsData data : goodsDatas)
        {
            if(!data.checkProp(cls, key, parentId))
                return false;
        }
        return true;
    }

    public static boolean checkAsset(GoodsData[] goodsDatas, Class cls, String key, int parentId)
    {
        for(GoodsData data : goodsDatas)
        {
            if(!data.checkAsset(cls, key, parentId))
                return false;
        }
        return true;
    }

    public static boolean checkGoods(GoodsData[] goodsDatas, Class cls, String key, int parentId)
    {
        for(GoodsData data : goodsDatas)
        {
            if(!data.check(cls, key, parentId))
                return false;
        }
        return true;
    }

    /**
     * 循环向上转型, 获取对象的 DeclaredField
     * @param object : 子类对象
     * @param fieldName : 父类中的属性名
     * @return 父类中的属性对象
     */

    public static Field getDeclaredField(Object object, String fieldName){
        Field field = null ;

        Class<?> clazz = object.getClass() ;

        for(; clazz != Object.class ; clazz = clazz.getSuperclass()) {
            try {
                field = clazz.getDeclaredField(fieldName) ;
                return field ;
            } catch (Exception e) {
                //这里甚么都不要做！并且这里的异常必须这样写，不能抛出去。
                //如果这里的异常打印或者往外抛，则就不会执行clazz = clazz.getSuperclass(),最后就不会进入到父类中了

            }
        }

        return null;
    }

    public static <T> List<T> loadJsonVariables(InputStream inputStream, Class<T> cls)
    {
        List<T> list = new CopyOnWriteArrayList<T>();
        BufferedReader br = null;
        try{
            br = new BufferedReader(new UnicodeReader(inputStream));
            String line = null;
            StringBuilder data = new StringBuilder();
            while((line = br.readLine()) != null) {
                data.append(line);
            }

            JSONObject jsonObject = JSONObject.parseObject(data.toString());
            JSONObject infoObj = null;
            for(String key : jsonObject.keySet())
            {
                infoObj = jsonObject.getJSONObject(key);

                T info = cls.newInstance();

                for(String fieldKey : infoObj.keySet())
                {
                    Field field = getDeclaredField(info, fieldKey);
                    if(field == null)
                    {
                        LogUtils.error("Field is null:" + fieldKey + " cls:" + cls);
                        continue;
                    }

                    ((GameObject)info).setVariable(fieldKey, infoObj.get(fieldKey).toString());
                }

                list.add(info);
            }

        }catch (Exception e){
            e.printStackTrace();
        }finally {
            try {
                if(br != null){
                    br.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

        return list;
    }

    public static <T> List<T> loadFileVariables(InputStream inputStream, Class<T> cls)
    {
        List<T> list = new CopyOnWriteArrayList<T>();
//        BufferedReader br = null;
        try{
            String fileContent = FileUtils.readFile(inputStream);
            String result = EncryptUtils.decode(fileContent);
            String[] ary = result.split(System.lineSeparator());
            String[] fieldStr = ary[0].split(ConstantFactory.TABLE);
            //1 是属性类型 2 是中文注释行 都不需要
            String key = "", value = "";
            boolean loadResult = false;
            for(int j = 3; j < ary.length; j++)
            {
                String[] values = ary[j].split(ConstantFactory.TABLE);
                T info = cls.newInstance();

                for(int i = 0; i < fieldStr.length; i++)
                {
                    key = fieldStr[i].trim();
                    Field field = getDeclaredField(info, key);
                    if(field == null)
                    {
//                        LogUtils.error("Field is null:" + key + " cls:" + cls);
                        continue;
                    }

                    if(i >= values.length)
                        value = "";
                    else
                        value = values[i].trim();

                    loadResult = ((GameObject) info).setVariable(key, value);

                    if(!loadResult)
                    {
                        DataFactory.getInstance(LoadFactory.isTestLoad()).addError(cls.getSimpleName(), key, value, ((GameObject)info).id);
                    }
                }
                list.add(info);
            }
//            br = new BufferedReader(new UnicodeReader(inputStream));
//            String line = null;
//
//            br.readLine();//属性类型，忽略
//            br.readLine();//中文注释行，忽略
//            boolean loadResult = true;
//            String key = "", value = "";
//            while((line = br.readLine()) != null) {
//                if(!line.equals(""))
//                {
//                    String[] values = line.split("\t");
//                    T info = cls.newInstance();
//
//                    for(int i = 0; i < fieldStr.length; i++)
//                    {
//                        key = fieldStr[i].trim();
//                        Field field = getDeclaredField(info, key);
//                        if(field == null)
//                        {
//                            LogUtils.error("Field is null:" + key + " cls:" + cls);
//                            continue;
//                        }
//
//                        if(i >= values.length)
//                            value = "";
//                        else
//                            value = values[i].trim();
//
//                        loadResult = ((GameObject)info).setVariable(key, value);
//
//                        if(!loadResult)
//                        {
//                            DataFactory.getInstance(LoadFactory.isTestLoad()).addError(cls.getSimpleName(), key, value, ((GameObject)info).id);
//                        }
//                    }
//                    list.add(info);
//                }
//            }

        }catch (Exception e){
            e.printStackTrace();
        }finally {
//            try {
//                if(br != null){
//                    br.close();
//                }
//            } catch (IOException e) {
//                e.printStackTrace();
//            }
        }

        return list;
    }

//    public static <T> List<T> loadFileVariables(InputStream inputStream, Class<T> cls)
//    {
//        List<T> list = new CopyOnWriteArrayList<T>();
//        BufferedReader br = null;
//        try{
//            br = new BufferedReader(new UnicodeReader(inputStream));
//            String line = null;
//            String[] fieldStr = br.readLine().split(ConstantFactory.TABLE);
//            br.readLine();//属性类型，忽略
//            br.readLine();//中文注释行，忽略
//            boolean loadResult = true;
//            String key = "", value = "";
//            while((line = br.readLine()) != null) {
//                if(!line.equals(""))
//                {
//                    String[] values = line.split("\t");
//                    T info = cls.newInstance();
//
//                    for(int i = 0; i < fieldStr.length; i++)
//                    {
//                        key = fieldStr[i].trim();
//                        Field field = getDeclaredField(info, key);
//                        if(field == null)
//                        {
//                            LogUtils.error("Field is null:" + key + " cls:" + cls);
//                            continue;
//                        }
//
//                        if(i >= values.length)
//                            value = "";
//                        else
//                            value = values[i].trim();
//
//                        loadResult = ((GameObject)info).setVariable(key, value);
//
//                        if(!loadResult)
//                        {
//                            DataFactory.getInstance(LoadFactory.isTestLoad()).addError(cls.getSimpleName(), key, value, ((GameObject)info).id);
//                        }
//                    }
//                    list.add(info);
//                }
//            }
//
//        }catch (Exception e){
//            e.printStackTrace();
//        }finally {
//            try {
//                if(br != null){
//                    br.close();
//                }
//            } catch (IOException e) {
//                e.printStackTrace();
//            }
//        }
//
//        return list;
//    }

    public static int[] loadIntArray(String key, String value)
    {
        int[] result = null;
        try{
            String[] strs = value.split(ConstantFactory.SEMICOLON);
            result = new int[strs.length];
            int i = 0;
            for(String v : strs)
            {
                result[i++] = Integer.parseInt(v);
            }
        }catch (Exception e){
            e.printStackTrace();
            LogUtils.error("Load Config Error key：" + key + " value：" + value);
        }

        return result;
    }

    public static long[] loadLongArray(String key,String value){

        long[] result = null;
        try{
            String[] strs = value.split(ConstantFactory.SEMICOLON);
            result = new long[strs.length];
            int i = 0;
            for (String v:strs){
                result[i++] = Long.valueOf(v);
            }
        }catch (Exception e){
            e.printStackTrace();
            LogUtils.error("load Config Error key:" + key + " value:" + value);
        }
        return result;
    }

    public static float[] loadFloatArray(String key, String value)
    {
        float[] result = null;
        try{
            String[] strs = value.split(ConstantFactory.SEMICOLON);
            result = new float[strs.length];
            int i = 0;
            for(String v : strs)
            {
                result[i++] = Float.parseFloat(v);
            }
        }catch (Exception e){
            e.printStackTrace();
            LogUtils.error("Load Config Error key：" + key + " value：" + value);
        }

        return result;
    }

    public static TimeData loadTimeData(String key,String value){
        TimeData timeData = null;
        try {
            timeData = TimeUtils.initTimeData(value);
        }catch (Exception e){
            e.printStackTrace();
            LogUtils.error("Load config error key: " + key + " value: " + value);
        }
        return timeData;
    }


    public static CommonData[] loadCommonDataToArray(String key, String value)
    {
        CommonData[] result = null;
        try{
            if(CoreUtils.isErrorValue(value))
                result = new CommonData[0];
            else
            {
                String[] strs = value.split(ConstantFactory.DIVISION);
                result = new CommonData[strs.length];
                int i = 0;
                for(String v : strs)
                {
                    result[i++] = new CommonData(v);
                }
            }
        }catch (Exception e){
            e.printStackTrace();
            LogUtils.error("Load Config Error key：" + key + " value：" + value);
        }

        return result;
    }

    public static int[] loadToArray(String key,String value){
        if(CoreUtils.isErrorValue(value)) {
            return new int[0];
        }
        int[] result = null;
        try{
            String[] strs = value.split(ConstantFactory.SEMICOLON);
            result = new int[strs.length];
            int i = 0;
            for (String str:strs){
                result[i++] = Integer.parseInt(str);
            }
        }catch (Exception e){
            e.printStackTrace();
            LogUtils.error("Load Config Error key:" + key + " value:" + value);
        }
        return result;
    }

    public static GoodsData[] loadGoodDataToArray(String key, String value)
    {
        if(CoreUtils.isErrorValue(value))
            return new GoodsData[0];

        GoodsData[] result = null;
        try{
            String[] strs = value.split(ConstantFactory.DIVISION);
            result = new GoodsData[strs.length];
            int i = 0;
            for(String v : strs)
            {
                result[i++] = new GoodsData(v);
            }
        }catch (Exception e){
            e.printStackTrace();
            LogUtils.error("Load Config Error key：" + key + " value：" + value);
        }

        return result;
    }

    public static DropObject[] loadDropObject(String value)
    {
        DropObject[] result = null;
        if(CoreUtils.isErrorValue(value)){
            result = new DropObject[0];
        }else{
            String[] strs = value.split(ConstantFactory.DIVISION);
            result = new DropObject[strs.length];
            for(int i = 0; i < strs.length; i++)
            {
                result[i] = new DropObject(strs[i]);
            }
        }
        return result;
    }




    public static List<CommonData> loadResourceToList(String value)
    {
        List<CommonData> result = null;
        try{
            String[] strs = value.split(ConstantFactory.DIVISION);
            result = new CopyOnWriteArrayList<>();
            for(String v : strs)
            {
                result.add(new CommonData(v));
            }
        }catch (Exception e){
            e.printStackTrace();
            LogUtils.error("Load Config Error:" + value);
        }

        return result;
    }


    public static int[] loadIntArray(String value)
    {
        int[] result = null;
        try{
            String[] strs = value.split(ConstantFactory.SEMICOLON);
            result = new int[strs.length];
            int i = 0;
            for(String v : strs)
            {
                result[i++] = Integer.parseInt(v);
            }
        }catch (Exception e){
            e.printStackTrace();
        }
        return result;
    }

    /**
     * 加载一个指定大小的随机名字表
     * @param num
     * @return
     */

    public static List<String> getRandomPlayerNameList(int num){
        List<String> list = new ArrayList<>();
        if(DataFactory.getInstance().getDataList(DataFactory.PLAYER_NAME_KEY).size() < num){
            return list;
        }

        while (true){
            String name = getRandomPlayerName();
            if(list.contains(name)){
                continue;
            }
            list.add(name);
            if(list.size() == num){
                break;
            }
        }
        return list;
    }

    /**
     * 加载一个随机名字
     * @return
     */
    public static String getRandomPlayerName(){
        List<PlayerNameConfig> dataList = DataFactory.getInstance().getDataList(DataFactory.PLAYER_NAME_KEY);
        if(dataList == null || dataList.isEmpty())
        {
            LogUtils.error("PLAYER_NAME is Null!");
            return "NULL_" + com.bean.core.util.Utils.getRandom(1000);
        }

        int first = com.bean.core.util.Utils.getRandom(dataList.size());
        int second = com.bean.core.util.Utils.getRandom(dataList.size());
        int third = com.bean.core.util.Utils.getRandom(dataList.size());
        return (dataList.get(first).name1 == null ? "" :  dataList.get(first).name1) +
                (dataList.get(second).name2 == null ? "" : dataList.get(second).name2 ) +
                (dataList.get(third).name3 == null ? "" : dataList.get(third).name3);
    }


}
